package com.nas.crocus.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.nas.crocus.dao.EventoDao;
import com.nas.crocus.domain.Alojamiento;
import com.nas.crocus.domain.Evento;
import com.nas.crocus.domain.Hotel;
import com.nas.crocus.domain.RegistroAlojamiento;
import com.nas.crocus.domain.RegistroPasajero;
import com.nas.crocus.exception.EntidadNoUnicaException;
import com.nas.crocus.service.EventoService;
import com.nas.crocus.service.HotelService;
import com.nas.crocus.service.RegistroAlojamientoService;
import com.nas.crocus.service.RegistroPasajeroService;
import com.nas.crocus.service.RutaService;

@Service
@Transactional
public class EventoServiceImpl implements EventoService {

    @Autowired
    private EventoDao eventoDao;
    
    @Autowired
    private HotelService hotelService;
    
    @Autowired
    private RutaService rutaService;
    
    @Autowired
    private RegistroPasajeroService registroPasajeroService;
    
    @Autowired
    private RegistroAlojamientoService registroAlojamientoService;
    
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public List<Evento> buscar() {       
        return eventoDao.buscar();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Evento buscar(Long eventoId) {
       return eventoDao.buscar(eventoId);
    }

    @Override
    public void guardar(Evento evento) {

        if (evento.getCantidadAsistentes() == null) {
            evento.setCantidadAsistentes(0);
        }
        
        if (evento.getAlojamientos() != null) {
            Hotel hotel;
            for (Alojamiento alojamiento : evento.getAlojamientos()) {
                hotel = alojamiento.getHotel();
                if ((hotel.getId() == null) || (hotel.getId().longValue() == 0)){
                    try {
                        hotelService.guardar(hotel);
                    } catch (EntidadNoUnicaException e) {
                        hotel = hotelService.buscarPorNombre(hotel.getNombre());
                    }
                    alojamiento.setHotel(hotel);
                    if (alojamiento.getCantidadHabitacionDoble() == null) {
                        alojamiento.setCantidadHabitacionDoble(0);
                    }
                    if (alojamiento.getCantidadHabitacionOtra() == null) {
                        alojamiento.setCantidadHabitacionOtra(0);
                    }
                    if (alojamiento.getCantidadHabitacionSimple() == null) {
                        alojamiento.setCantidadHabitacionSimple(0);
                    }
                }            
            }
        }
       
        
        evento.getRuta().setEvento(evento);
        eventoDao.guardar(evento);

        RegistroPasajero registroPasajero = new RegistroPasajero();
        registroPasajero.setCantidadAsistentes(0);
        registroPasajero.setEvento(evento);
        registroPasajeroService.guardar(registroPasajero);
        
        for (Alojamiento alojamiento : evento.getAlojamientos()) {
            registroAlojamientoService.crearRegistro(alojamiento.getId());
        }
       
    }

    @Override
    public void actualizar(Evento evento) {
        Evento eventoExistente = this.buscar(evento.getId());

        eventoExistente.setCantidadAsistentes(evento.getCantidadAsistentes());
        eventoExistente.setEmpresa(evento.getEmpresa());
        eventoExistente.setFechaFin(evento.getFechaFin());
        eventoExistente.setFechaInicio(evento.getFechaInicio());
        eventoExistente.setNombre(evento.getNombre());
        eventoExistente.setSupervisorMail(evento.getSupervisorMail());
        eventoExistente.setSupervisorNombre(evento.getSupervisorNombre());
        
        mergeAlojamientos(evento, eventoExistente);
        
        if (evento.getRuta() != null) {
            evento.getRuta().setEvento(eventoExistente);
            if (evento.getRuta().getId() != null) {
                rutaService.actualizar(evento.getRuta());
            } else {
                rutaService.crear(evento.getRuta());
            }
        }
        eventoDao.actualizar(eventoExistente); 
        for (Alojamiento alojamiento : eventoExistente.getAlojamientos()) {
            registroAlojamientoService.crearRegistro(alojamiento.getId());
        }
    }

    
    
    private void mergeAlojamientos(Evento evento,
            Evento eventoExistente) {
        Collection<Alojamiento> alojamientosExistentes = eventoExistente.getAlojamientos(); 
        ArrayList<Alojamiento> alojamientosCreados = new ArrayList<Alojamiento>();
        ArrayList<Alojamiento> alojamientosModificados = new ArrayList<Alojamiento>();
        ArrayList<Alojamiento> alojamientosEliminados = new ArrayList<Alojamiento>();
        boolean eliminarAlojamiento = false;
        
        for (Alojamiento alojamiento : evento.getAlojamientos()) {
            if (alojamiento.getId() == null) {
                alojamiento.setEvento(eventoExistente);
                alojamientosCreados.add(alojamiento);            
            } else {
                alojamientosModificados.add(alojamiento);
            }
            
            if (alojamiento.getCantidadHabitacionDoble() == null) {
                alojamiento.setCantidadHabitacionDoble(0);
            }
            if (alojamiento.getCantidadHabitacionOtra() == null) {
                alojamiento.setCantidadHabitacionOtra(0);
            }
            if (alojamiento.getCantidadHabitacionSimple() == null) {
                alojamiento.setCantidadHabitacionSimple(0);
            }
        }
        Hotel hotel;
        for (Alojamiento alojamientoExistente : alojamientosExistentes) {
            eliminarAlojamiento = true;
            for (Alojamiento alojamiento : alojamientosModificados) {
                if (alojamiento.getId().longValue() == alojamientoExistente.getId().longValue()) {
                    alojamientoExistente.setCantidadHabitacionDoble(alojamiento.getCantidadHabitacionDoble());
                    alojamientoExistente.setCantidadHabitacionOtra(alojamiento.getCantidadHabitacionOtra());
                    alojamientoExistente.setCantidadHabitacionSimple(alojamiento.getCantidadHabitacionSimple());
                    
                    hotel = alojamiento.getHotel();
                    if (hotel.getId() == null || hotel.getId() == 0) {
                        try {
                            hotelService.guardar(hotel);
                        } catch (EntidadNoUnicaException e) {
                            hotel = hotelService.buscarPorNombre(hotel.getNombre());
                        }
                    } else {
                        alojamientoExistente.setHotel(hotelService.buscar(alojamiento.getHotel().getId()));  
                    }
                    alojamientoExistente.setVencimiento1(alojamiento.getVencimiento1());
                    alojamientoExistente.setVencimiento2(alojamiento.getVencimiento2());
                    alojamientoExistente.setVencimiento3(alojamiento.getVencimiento3());
                    eliminarAlojamiento = false;
                    break;
                }                
            }
            if (eliminarAlojamiento) {
                alojamientosEliminados.add(alojamientoExistente);                
            }
        }
        for (Alojamiento alojamientoAEliminar : alojamientosEliminados) {
            alojamientosExistentes.remove(alojamientoAEliminar);
            registroAlojamientoService.eliminarPorAlojamientoId(alojamientoAEliminar.getId());
        }
               
        alojamientosExistentes.addAll(alojamientosCreados);
    }

    
}
